package dataediter;

import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.stream.Stream;

/**
 * 读写数据基类
 *
 * @author fdh
 */
public class FileWRBase {

    // region 回调函数

    /**
     * 写入信息
     */
    public interface WriteInfo {
        /**
         * 判断写入条件
         *
         * @param line 文本中的当前行
         * @return 是否在此写入
         */
        boolean search(String line);

        /**
         * 写入的内容
         *
         * @return 需要写入的内容
         */
        String write();
    }

    /**
     * 读取信息
     */
    public interface ReadInfo {
        /**
         * 判断读取条件
         *
         * @param line 文本中的当前行
         * @return 是否读取成功
         */
        boolean search(String line);
    }

    /**
     * 获取符合要求的全部行
     */
    public interface ReadAll {
        /**
         * 判断开始读取的条件
         *
         * @param line 文本当前行
         * @return 是否开始读取
         */
        boolean start(String line);

        /**
         * 判断结束读取的条件
         *
         * @param line 文本当前行
         * @return 是否结束读取
         */
        boolean end(String line);
    }
    //endregion

    // region 写入文件

    /**
     * 写入数据在指定行
     *
     * @param filePath  文件路径
     * @param writeInfo 回调函数
     */
    public void writeInfoToTargetLine(String filePath, WriteInfo writeInfo) {
        StringBuilder sb = new StringBuilder();
        try (BufferedReader br = new BufferedReader(new FileReader(filePath))) {
            String line;
            while ((line = br.readLine()) != null) {
                if (writeInfo.search(line)) {
                    sb.append(writeInfo.write()).append("\n");
                }
                sb.append(line).append("\n");
            }
        } catch (Exception e) {
            System.out.println("读取失败:" + filePath);
            return;
        }
        try (BufferedWriter bw = new BufferedWriter(new FileWriter(filePath))) {
            bw.write(sb.toString());
            System.out.println("写入成功:" + filePath);
        } catch (Exception e) {
            System.out.println("写入失败:" + filePath);
        }
    }

    /**
     * 写入指定数据
     *
     * @param filePath
     * @param list     数据集
     */
    public void writeAllData(String filePath, ArrayList<String> list) {
        try (BufferedWriter bw = new BufferedWriter(new FileWriter(filePath))) {
            StringBuilder sb = new StringBuilder();
            for (String s : list) {
                sb.append(s).append("\n");
            }
            bw.write(sb.toString());
            System.out.println("写入成功:" + filePath);
        } catch (Exception e) {
            System.out.println("写入失败:" + filePath);
        }
    }

    /**
     * 写入指定数据
     *
     * @param path
     * @param data
     */
    public void writeAllData(String path, String data) {
        try (BufferedWriter bw = new BufferedWriter(new FileWriter(path))) {
            bw.write(data);
        } catch (Exception e) {
            System.out.println("写入失败:" + path);
        }
    }
    //endregion

    // region 读取文件

    /**
     * 读取数据并比对是否存在
     *
     * @param filePath 文件路径
     * @param readInfo 回调函数
     * @return 数据中是否存在查找的数据
     */
    public boolean isInfoInFile(String filePath, ReadInfo readInfo) {
        try (BufferedReader br = new BufferedReader(new FileReader(filePath))) {
            String line;
            while ((line = br.readLine()) != null) {
                if (readInfo.search(line)) {
                    return true;
                }
            }
            System.out.println("读取成功:" + filePath);
            return false;
        } catch (Exception e) {
            System.out.println("读取失败:" + filePath);
            return false;
        }
    }

    /**
     * 返回指定区间内的全部数据,不包含开头结尾
     *
     * @param filePath 文件路径
     * @param readAll  回调函数
     * @return 全部指定数据
     */
    public ArrayList<String> readAll(String filePath, ReadAll readAll) {
        ArrayList<String> list = new ArrayList<>();
        boolean isStart = false;
        try (BufferedReader br = new BufferedReader(new FileReader(filePath))) {
            String line;
            while ((line = br.readLine()) != null) {
                if (readAll.start(line)) {
                    isStart = true;
                    continue;
                }
                if (readAll.end(line)) {
                    break;
                }
                if (isStart) {
                    list.add(line);
                }
            }
            System.out.println("读取成功:" + filePath);
            return list;
        } catch (Exception e) {
            System.out.println("读取失败:" + filePath);
            return null;
        }
    }

    /**
     * 读取指定文件的全部行
     *
     * @param filePath
     * @return
     */
    public ArrayList<String> readAll(String filePath) {
        ArrayList<String> list = new ArrayList<>();
        try (BufferedReader br = new BufferedReader(new FileReader(filePath))) {
            String line;
            while ((line = br.readLine()) != null) {
                list.add(line);
            }
            System.out.println("读取成功:" + filePath);
            return list;
        } catch (Exception e) {
            System.out.println("读取失败:" + filePath);
            return null;
        }
    }
    //endregion

    // region 创建文件

    /**
     * 创建文件
     *
     * @param filePath 文件地址
     */
    public boolean createFile(String filePath) {
        try {
            if (Files.exists(Paths.get(filePath))) {
                System.out.println("文件创建失败,已经存在:" + filePath);
                return false;
            } else {
                Files.createFile(Paths.get(filePath));
                System.out.println("文件创建成功:" + filePath);
                return true;
            }
        } catch (Exception e) {
            System.out.println("文件创建失败:" + filePath);
            return false;
        }
    }
    //endregion

    // region 删除文件

    /**
     * 删除文件
     *
     * @param path 路径
     * @return 是否成功删除
     */
    public boolean delFile(String path) {
        try {
            Files.delete(Paths.get(path));
            return true;
        } catch (Exception e) {
            System.out.println("删除失败:" + path);
            return false;
        }
    }
    //endregion

    // region 扫描目录

    /**
     * 扫描目录
     *
     * @param path       目录
     * @param suffixName 目标文件的后缀名,不带 '.'
     * @return 目录下全部目标文件名
     */
    public static ArrayList<String> scanDirectory(String path, String suffixName) {
        ArrayList<String> fileNames = new ArrayList<>();
        try {
            if (Files.exists(Paths.get(path))) {
                Stream<Path> allPath = Files.list(Paths.get(path));
                allPath.forEach(path1 -> {
                    if (Files.isRegularFile(path1)) {
                        if (path1.getFileName().toString()
                                .contains("." + suffixName)
                        ) {
                            fileNames.add(path1.getFileName().toString());
                        }
                    }
                });
                return fileNames;
            } else {
                System.out.println("扫描失败,路径不存在");
                return null;
            }
        } catch (Exception e) {
            System.out.println("扫描失败");
            return null;
        }
    }

    /**
     * 扫描目录
     *
     * @param path       目录
     * @param suffixName 目标文件的后缀名,不带 '.'
     * @param fileNames  存储目标文件的结构
     */
    public static void scanDirectory(String path, String suffixName, ArrayList<String> fileNames) {
        try {
            if (Files.exists(Paths.get(path))) {
                Stream<Path> allPath = Files.list(Paths.get(path));
                allPath.forEach(path1 -> {
                    if (Files.isRegularFile(path1)) {
                        if (path1.getFileName().toString()
                                .contains("." + suffixName)
                        ) {
                            fileNames.add(path1.getFileName().toString());
                        }
                    }
                });
            } else {
                System.out.println("路径不存在:" + path);
            }
        } catch (Exception e) {
            System.out.println("扫描失败:" + path);
        }
    }
    //endregion
}
